package com.glsc.ngateway.oaflow.controller;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.oaflow.dto.param.ParamOaLoginDto;
import com.glsc.ngateway.common.api.oaflow.resp.CommonResponse;
import com.glsc.ngateway.common.api.oaflow.resp.ResponseLoginDto;
import com.glsc.ngateway.common.api.wordconver.feign.IFeignWordconverService;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

@RestController
public class OaLoginController {

    private Logger logger = LoggerFactory.getLogger(OaLoginController.class);

    //wkhtmltopdf在系统中的路径
    private static final String toPdfToolWindows = "C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf";
    private static final String toPdfToolLinux = "/usr/local/bin/wkhtmltopdf";

    @Autowired
    private RestTemplate restTemplate;

    @Value("${oalogin.host}")
    public String host;
    @Value("${oalogin.destPath}")
    public String destPath;

    @Autowired
    private IFeignWordconverService wordconverService;

    @RequestMapping(method = RequestMethod.POST, value = "getOaWorkflowPic")
    public CommonResponse getOaWorkflowPic(@RequestParam String requestid, @RequestParam(required = false) String wfid, @RequestBody ParamOaLoginDto params) throws Exception {

        String sessionId = null;
        CommonResponse<ResponseLoginDto> login = oaLogin(params);
        if (login == null) {
            return CommonResponse.error("getOaWorkflowPic模拟登录失败");
        }
        if (login.getData() == null) {
            return CommonResponse.error("getOaWorkflowPic模拟登录失败");
        }
        if (StringUtils.isNotEmpty(login.getData().getSessionId())) {
            sessionId = login.getData().getSessionId();
        } else {
            return CommonResponse.error("getOaWorkflowPic模拟登录失败");
        }
        String ecogySession = MessageFormat.format("JSESSIONID={0}; ecology_JSessionid={1};", sessionId, sessionId);
        String urlRequest = host + "/workflow/design/workflowPicDisplayData.jsp";
        Map<String, String> headMap = new HashMap<>();
        headMap.put(HttpHeaders.COOKIE, ecogySession); //将cookie放入header
//        headMap.put(HttpHeaders.REFERER, urlRequest);
//        headMap.put(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate");
        MultiValueMap<String, Object> postParams = new LinkedMultiValueMap<>();
        ResponseEntity<String> requestPageInfo = requestForm(urlRequest + "?requestid=" + requestid + "&wfid=" + wfid, postParams, headMap, HttpMethod.POST);
        if (HttpStatus.OK.equals(requestPageInfo.getStatusCode())) {
            return CommonResponse.success(requestPageInfo.getBody().trim());
        } else {
            return CommonResponse.error("sessionId无效");
        }
    }

    /**
     * 获取流程图（新接口）
     *
     * @param requestid
     * @param wfid
     * @param params
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "getOaWorkflowPicNew")
    public ResponseEntity<byte[]> getOaWorkflowPicNew(@RequestParam String requestid, @RequestParam(required = false) String wfid, @RequestBody ParamOaLoginDto params) throws Exception {
        String sessionId = null;
        CommonResponse<ResponseLoginDto> login = oaLogin(params);
        //getOaWorkflowPic模拟登录失败
        if (login == null || login.getData() == null || StringUtils.isBlank(login.getData().getSessionId())) {
            return ResponseEntity.badRequest().build();
        }
        sessionId = login.getData().getSessionId();
        String srcPath = host + "/workflow/workflowDesign/readOnly-index.html?requestid=" + requestid + "&workflowid=" + wfid + "&isFromWfForm=true";
        ResponseEntity<byte[]> responseEntity = wordconverService.getPdfFromOaUrl(srcPath, sessionId);
        if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "attachment;filename=" + UUID.randomUUID() + ".pdf");
            return new ResponseEntity<>(responseEntity.getBody(), headers, HttpStatus.OK);
        } else {
            return new ResponseEntity<>(null, new HttpHeaders(), HttpStatus.OK);
        }
    }

    @RequestMapping(method = RequestMethod.POST, value = "checkOaSession")
    public CommonResponse checkOaSession(@RequestParam String sessionId) {

        String ecogySession = MessageFormat.format("JSESSIONID={0}; ecology_JSessionid={1};", sessionId, sessionId);
        String urlPrintRequest = host + "/wui/main.jsp?templateId=1";
        Map<String, String> headMap = new HashMap<>();
        headMap.put(HttpHeaders.COOKIE, ecogySession); //将cookie放入header
        headMap.put(HttpHeaders.REFERER, urlPrintRequest);
        headMap.put(HttpHeaders.ACCEPT, MediaType.TEXT_HTML_VALUE);

        MultiValueMap<String, Object> postParams = new LinkedMultiValueMap<>();
        ResponseEntity<String> requestPageInfo = requestForm(urlPrintRequest, postParams, headMap, HttpMethod.GET);

        if (requestPageInfo.toString().contains("国联证券股份有限公司")) {
            return CommonResponse.success(null);
        } else {
            return CommonResponse.error("sessionId无效");
        }
    }


    @RequestMapping(method = RequestMethod.POST, value = "oaLogin")
    public CommonResponse<ResponseLoginDto> oaLogin(@RequestBody ParamOaLoginDto params) throws Exception {
        //1.模拟OA登录
        MultiValueMap<String, Object> postParams = new LinkedMultiValueMap<>();
        //用户名=>改为配置格式
        postParams.add("loginid", params.getLoginid());
        //明文密码=>改为配置方式，使用base64或者其它加密算法隐藏以下明文
        postParams.add("userpassword", new String(Base64.decodeBase64(params.getUserpassword())));
        //OA登录此字段固定
        postParams.add("logintype", "1");
        Map<String, String> headMap = new HashMap<>();
        ResponseEntity<String> conn = requestForm(host + "/api/hrm/login/checkLogin", postParams, headMap, HttpMethod.POST);
        if (conn == null) {
            logger.error("OA模拟登录失败！");
            return CommonResponse.success(new ResponseLoginDto());
        }
        Map<String, String> map = JSONObject.parseObject(conn.getBody(), Map.class);
        if (Objects.isNull(map) || "false".equals(map.getOrDefault("loginstatus", "false")) || !conn.getHeaders().containsKey(HttpHeaders.SET_COOKIE)) {
            logger.error("OA模拟登录失败！:{}", Objects.isNull(map) ? "non response body" : map.getOrDefault("msg", "none"));
            return CommonResponse.success(new ResponseLoginDto());
        }
        logger.info("OA模拟登录返回head:{}, body:{}", conn.getHeaders(), conn.getBody());
        ResponseLoginDto resp = ResponseLoginDto.convertFromHttpCookie(conn.getHeaders().get(HttpHeaders.SET_COOKIE));
        if (Strings.isNotBlank(resp.getClusterSessionIDCookieName()) || Strings.isNotBlank(resp.getSessionId())) {
            logger.info("OA模拟登录成功，con:{}, head:{}, jsessionid={}", conn, conn.getHeaders().get(HttpHeaders.SET_COOKIE), resp.getClusterSessionIDCookieName());
            resp.setSessionId(Strings.isNotBlank(resp.getClusterSessionIDCookieName()) ? resp.getClusterSessionIDCookieName() : resp.getSessionId());
            return CommonResponse.success(resp);
        } else {
            logger.error("OA模拟登录失败！:未解析到session, resp:{}", resp);
            return CommonResponse.success(new ResponseLoginDto());
        }
    }


    /**
     * POST请求调用方式
     *
     * @param url         请求URL
     * @param requestForm 请求表单
     * @return ResponseEntity 响应对象封装类
     */
    private ResponseEntity<String> requestForm(String url, MultiValueMap<String, Object> requestForm, Map<String, String> headersMap, HttpMethod method) throws RestClientException {

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
        headers.add(HttpHeaders.ACCEPT, MediaType.ALL_VALUE);

        if (!MapUtil.isEmpty(headersMap)) {
            for (Map.Entry<String, String> entry : headersMap.entrySet()) { //填充headers
                headers.add(entry.getKey(), entry.getValue());
            }
        }
        HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(requestForm, headers);
//        requestForm.remove("userpassword");
        logger.info("请求：" + formEntity + "," + url);
        ResponseEntity<String> respEntity = restTemplate.exchange(url, method, formEntity, String.class);
        logger.info("返回状态码：" + respEntity.getStatusCodeValue());
        if (HttpStatus.OK.value() == respEntity.getStatusCodeValue()) {
            return respEntity;
        } else {
            return null;
        }
    }


    /**
     * html转pdf
     *
     * @param srcPath html路径，可以是硬盘上的路径，也可以是网络路径
     * @return 转换成功返回true
     */
    @RequestMapping(method = RequestMethod.POST, value = "htmlToPdf")
    public ResponseEntity<byte[]> htmlToPdf(@RequestParam String srcPath, @RequestParam String sessionId, HttpServletRequest request) throws Exception {
//        File file = oaLoginService.createFileFromHtml(srcPath, sessionId);
//        if (file == null) {
//            return new ResponseEntity<byte[]>(null, new HttpHeaders(), HttpStatus.OK);
//        }
//        return oaLoginService.getFileStream(file, request);

        ResponseEntity<byte[]> responseEntity = wordconverService.getPdfFromOaUrl(host + srcPath, sessionId);
        if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "attachment;filename=" + UUID.randomUUID() + ".pdf");
            return new ResponseEntity<>(responseEntity.getBody(), headers, HttpStatus.OK);
        } else {
            return new ResponseEntity<>(null, new HttpHeaders(), HttpStatus.OK);
        }
    }


}
